/*=============================================================================
#    The element-comm is a tentative program used to test our ideas.           
#                       Copyright (C)  bgao                                    
#
#     This program is free software; you can redistribute it and/or            
#      modify it under the terms of the GNU General Public License             
#     as published by the Free Software Foundation; either version 2           
#         of the License, or (at your option) any later version.               
#
#     This program is distributed in the hope that it will be useful,          
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            
#             GNU General Public License for more details.                    
#
#    You should have received a copy of the GNU General Public License        
#     along with this program; if not, write to the Free Software             
#      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,             
#                       MA  02110-1301, USA.                                  
#==============================================================================
# $Id: list.c 348 2010-11-29 09:01:16Z bgao $ 
#
# $Author: bgao $ 
#
# $Revision: 348 $ 
#
# $Date: 2010-11-29 17:01:16 +0800 (星期一, 29 十一月 2010) $ 
#
# Description: 
#
=============================================================================*/
/*! @file list.c
 *  @brief This is an implementation of general list.
 */
#include "list.h"

/*! initialize the list.
 *  @param list the pointer to the header of the list.
 */
char list_init(list_t list)
{
    /* check if the list is declared by LIST macro. */
    if (list == NULL) {
        return LIST_ERR;
    }

    *list = NULL;
    return LIST_OK;
}

/*! add an item to the end of the list.
 *  @param list the pointer to the header of the list.
 *  @param item the pointer to the item to be added.
 *  @return -1 if either list is NULL or the item is NULL,
 *       else return 0.
 */
char list_add_tail(list_t list, void *item)
{
    list_item_t *v = NULL;

    if (item == NULL)
        return LIST_ERR;

    v = (list_item_t *)*list;

    /* the list is empty. */
    if (v == NULL) {          
        v = (list_item_t *)item;
        v->next = NULL;
        *list = v;
        return LIST_OK;
    }

    /* find the last item of the list. */
    for (; v->next != NULL; v = v->next)
        ;

    v->next = (list_item_t *)item;  
    ((list_item_t *)item)->next = NULL; 

    return LIST_OK;
}

/*! return the first item of the list.
 *  @param list the pointer to the header of the list.
 *  @return the pointer to the header of the list
 *       or NULL if the list is empty.
 */
void *list_get_head(list_t list)
{
    if (*list == NULL)
        return NULL;

    return *list;
}

/*! return the last item of the list.
 *  @param list the pointer to the header of the list.
 *  @return pointer to the last item of the list.
 *       or NULL if the list is empty.
 */ 
void *list_get_tail(list_t list)
{
    list_item_t *v;

    if (*list == NULL) {
        return NULL;
    }

    for (v = (list_item_t *)*list; v->next != NULL; v = v->next)
        ;
    return v;
}

/*! add an item to the head of the list.
 *  @param list the pointer to the header of the list.
 *  @param item the pointer to the item to be added.
 *  @return -1 if either list is NULL or the item is NULL,
 *       else return 0.
 */
char list_add_head(list_t list, void *item)
{
    list_item_t *v; 

    if (item == NULL)
        return LIST_ERR;

    if (*list == NULL) {
        *list = item;
        ((list_item_t *)item)->next = NULL;
        return LIST_OK;
    }

    v = *list;
    ((list_item_t *)item)->next = v;
    *list = item;
    return LIST_OK;
}

/*! @param list the pointer to the header of the list.
 *  @return true if the list is empty, else false.   
 */
bool list_is_empty(list_t list)
{
    if (*list == NULL) {
        return true;
    }

    return false;
}

/*! get the length of the list.
 *  @param list the pointer to the header of the list.
 *  @return the total number of items of this list.
 */
short list_get_length(list_t list)
{
    short n = 0; 
    list_item_t *v;

    if (*list == NULL)
        return n;
    else 
        n = 1;

    for (v = (list_item_t *)*list; v->next != NULL; v = v->next) {
        n++;
    }
    
    return n;
}

/*! delete the item specified by item.
 *  @param list the pointer to the header of the list.
 *  @param item pointer to the item to be deleted.
 *  @return return the pointer to the item being deleted.
 *       or NULL if the list is empty.
 */
void *list_del(list_t list, void *item)
{
    list_item_t *v;   /*!< pointer to item previous the one to be delete. */
    list_item_t *d;   /*!< pointer to the item to be delete. */

    if (*list == item) {
        d = *list;
        *list = d->next;
        return d;
    }

    for (v = (list_item_t *)*list;
        (v->next != NULL) && (v->next != item); v = v->next)
        ;

    if (v->next != NULL) {
        d = v->next;
        v->next = d->next;
        d->next = NULL;
        return d;
    }

    /*!< either raech the tail of the list or doesn't have this item. */
    return NULL;
}

/*! delete the head item of the list.
 *  @param list the pointer to the header of the list.
 *  @return pointer to the deleted head of the list
 *       or NULL if the list is empty.
 */
void *list_del_head(list_t list)
{
    list_item_t *v;

    if (list == NULL || *list == NULL)
        return NULL;
    
    v = *list;
    *list = v->next;
    v->next = NULL;

    return v;
} 

